﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using test;


namespace test
{
    public partial class Data : Form
    {
        private DataTable dt; // 将 dt 声明为类的字段


        private TcpClient tcpClient; // 保存 TcpClient 引用
        private Form1 mainForm; // 存储 Form1 的实例
        public ushort send_transactionId = 1; // 事务 ID，可根据需要更改
        public ushort functionCode = 3;     // 默认为功能码 03H
        public int[] regs_data = new int[0];
        public int reg_read_click = 0; // 事务 ID，可根据需要更改
        public int loop_read = 0;







        private async Task ListenForResponsesAsync()
        {
            while (tcpClient != null && tcpClient.Connected && reg_read_click == 1)
            {
                reg_read_click = 0;
                try
                {   //获取网络流以进行数据读取
                    NetworkStream stream = tcpClient.GetStream();
                    //创建一个字节数组，接收响应报文
                    byte[] response = new byte[256];
                    // 清空 response 数组
                    Array.Clear(response, 0, response.Length);
                    //从网络流中读取数据，返回实际读取的字节数
                    int bytesRead = await stream.ReadAsync(response, 0, response.Length);



                    if (bytesRead > 0)
                    {
                        // 处理响应数据
                        ProcessResponse(response.Take(bytesRead).ToArray());
                    }
                }
                catch (Exception ex)
                {
                    // 显示错误消息并退出循环
                    MessageBox.Show("读取响应失败：" + ex.Message);
                    break; // 退出循环
                }


            }

            //其中的内部方法
            void ProcessResponse(byte[] response)
            {
                if (response.Length < 9)
                {
                    // MessageBox.Show("响应数据太短");
                    Loop_To_Success();
                    return;
                }

                ushort get_transactionId = BitConverter.ToUInt16(response, 0);
                ushort protocolId = BitConverter.ToUInt16(response, 2);
                ushort length = BitConverter.ToUInt16(response, 4);
                byte unitId = response[6];
                byte get_functionCode = response[7];
                byte byteCount = response[8];  // 正确：数据字节数（不是 ushort）

                if (response.Length < 9 + byteCount)
                {
                    // MessageBox.Show("响应数据不完整");
                    Loop_To_Success();
                    return;
                }
                switch (get_functionCode)
                {
                    case 0x01: // 线圈状态
                        ProcessCoilResponse(response, byteCount);
                        break;
                    case 0x02: // 线圈状态
                        ProcessCoilResponse(response, byteCount);
                        break;
                    case 0x03: // 保持寄存器
                        ProcessRegisterResponse(response, byteCount);
                        break;
                    case 0x04: // 保持寄存器
                        ProcessRegisterResponse(response, byteCount);
                        break;
                    // 其他功能码处理...
                    default:
                        MessageBox.Show("未知功能码");
                        break;
                }
            }

            void ProcessCoilResponse(byte[] response, byte byteCount)
            {
                // 实际线圈数量 = 用户请求的数量
                int coilCount = int.Parse(reg_qulity.Text);

                // 调整数组大小
                Array.Resize(ref regs_data, coilCount);

                // 每个字节存放 8 个线圈
                for (int i = 0; i < coilCount; i++)
                {
                    int byteIndex = 9 + (i / 8);   // 9 是数据起始位置
                    int bitIndex = i % 8;

                    byte coilByte = response[byteIndex];
                    regs_data[i] = (coilByte & (1 << bitIndex)) != 0 ? 1 : 0;
                }

                Reg_Upload_coils();
            }







            void ProcessRegisterResponse(byte[] response, byte byteCount)
            {
                int registerCount = byteCount / 2;
                Array.Resize(ref regs_data, registerCount);

                for (int i = 0; i < registerCount; i++)
                {
                    byte highByte = response[9 + (i * 2)];
                    byte lowByte = response[9 + (i * 2) + 1];
                    regs_data[i] = (highByte << 8) | lowByte;
                }

                Reg_Upload_registers();
            }



            void Loop_To_Success()




            {
                while (loop_read < 3)
                {
                    loop_read++;
                    SendModbusRequest(false);  // 👈 这里禁止自动监听
                }
                loop_read = 0;
                
            }


            void Reg_Upload_registers()
            {
                // 仅在 regs_data 中的数据有效时进行更新
                if (regs_data.Length > 0)
                {
                    dt.Clear(); // 清空现有数据

                    // 根据 reg_qulity 的值来决定添加的行数
                    int quality = Math.Min(int.Parse(reg_qulity.Text), regs_data.Length);

                    for (int i = int.Parse(reg_startaddress.Text); i < quality; i++)
                    {
                        dt.Rows.Add(i, regs_data[i]);
                    }
                }
                else
                {

                    Loop_To_Success();
                    //MessageBox.Show("没有可用的数据来更新表格。");
                }

            }

            void Reg_Upload_coils()
            {
                // 仅在 regs_data 中的数据有效时进行更新
               
                
                    dt.Clear(); // 清空现有数据

                    // 根据 reg_qulity 的值来决定添加的行数
                    int quality = int.Parse(reg_qulity.Text);

                    for (int i = int.Parse(reg_startaddress.Text); i < quality; i++)
                    {
                        dt.Rows.Add(i, regs_data[i]);
                    }


            }
        }






        public Data(Form1 form, TcpClient client)
        {
            InitializeComponent();
            this.Load += new EventHandler(Form1_Load);
            tcpClient = client;
            mainForm = form;
            this.reg_kind.DataSource = new string[] { "Reg_Coil", "Reg_Input_Disc", "Reg_Holding", "Reg_Input" };

            // 创建和设置控件

            // 将控件添加到窗体
            this.Controls.Add(reg_kind);
            this.Controls.Add(reg_startaddress);
            this.Controls.Add(reg_qulity);
            this.Controls.Add(reg_read);
            // 启动异步监听



        }


        public void SendModbusRequest(bool autoListen = true)
        {
            if (tcpClient == null || !tcpClient.Connected)
            {
                MessageBox.Show("请先连接到服务器。");
                return;
            }

            byte functionCode;
            switch (reg_kind.Text)
            {
                case "Reg_Coil":
                    functionCode = 0x01; // 读线圈
                    break;
                case "Reg_Input_Disc":
                    functionCode = 0x02; // 读离散输入
                    break;
                case "Reg_Holding":
                    functionCode = 0x03; // 读保持寄存器
                    break;
                case "Reg_Input":
                    functionCode = 0x04; // 读输入寄存器
                    break;
                default:
                    MessageBox.Show("未知寄存器类型");
                    return;
            }

            // 构建 Modbus TCP 请求
            byte[] request = new byte[12];
            send_transactionId = 1; // 事务 ID，可根据需要更改
            ushort protocolId = 0;     // 协议 ID
            ushort length = 6;         // 后续字节数
            byte unitId = 1;           // 单元 ID

            ushort startingAddress = ushort.Parse(this.reg_startaddress.Text);
            ushort registerCount = ushort.Parse(reg_qulity.Text);

            request[0] = (byte)(send_transactionId >> 8);
            request[1] = (byte)(send_transactionId & 0xFF);
            request[2] = (byte)(protocolId >> 8);
            request[3] = (byte)(protocolId & 0xFF);
            request[4] = (byte)(length >> 8);
            request[5] = (byte)(length & 0xFF);
            request[6] = unitId;
            request[7] = functionCode;
            request[8] = (byte)(startingAddress >> 8);
            request[9] = (byte)(startingAddress & 0xFF);
            request[10] = (byte)(registerCount >> 8);
            request[11] = (byte)(registerCount & 0xFF);

            NetworkStream stream = tcpClient.GetStream();
            stream.Write(request, 0, request.Length);

            reg_read_click = 1;

            // 👇 只有在 autoListen = true 的时候才启动监听
            if (autoListen)
            {
                _ = ListenForResponsesAsync();
            }
        }



        public void Form1_Load(object sender, EventArgs e)
        {
            Console.WriteLine("Form1_Load is executed");

            dt = new DataTable();
            dt.Columns.Add("地址");
            dt.Columns.Add("值");

            //初始化
            for (int i = 0; i <= 10; i++)
            {
                dt.Rows.Add(i, "0");
            }



            reg_data.DataSource = dt;
            reg_data.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
            reg_data.RowHeadersVisible = false;
        }


        private void ConfigForm0_Load(object sender, EventArgs e)
        {

        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {

        }

        private void reg_read_Click(object sender, EventArgs e)
        {
            MessageBox.Show("请求已发送");

            SendModbusRequest();

        }

        private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {

        }

        private void tableLayoutPanel1_Paint(object sender, PaintEventArgs e)
        {

        }

        private void label2_Click(object sender, EventArgs e)
        {

        }

        private void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void dataBindingSource_CurrentChanged(object sender, EventArgs e)
        {

        }

        private void reg_qulity_TextChanged(object sender, EventArgs e)
        {
            dt.Clear();
            for (int i = 0; i <= (int.Parse(reg_qulity.Text)); i++)
            {

                dt.Rows.Add(i, "0");
            }

        }

        private void reg_qulity_MaskInputRejected(object sender, MaskInputRejectedEventArgs e)
        {

        }

        private void reg_kind_chage(object sender, EventArgs e)
        {

            //"Reg_Coil", "Reg_Input_Disc", "Reg_Holding", "Reg_Input"
            switch (reg_kind.Text)
            {
                case "Reg_Coil":
                    // 针对 Reg_Coil 的操作
                    functionCode = 1;
                    // 例如，您可以设置某些控件的状态或执行特定的逻辑
                    break;

                case "Reg_Input_Disc":
                    // 针对 Reg_Input_Disc 的操作
                    functionCode = 2;
                    // 例如，您可以设置某些控件的状态或执行特定的逻辑
                    break;

                case "Reg_Holding":
                    // 针对 Reg_Holding 的操作
                    functionCode = 3;
                    // 例如，您可以设置某些控件的状态或执行特定的逻辑
                    break;

                case "Reg_Input":
                    functionCode = 4;
                    break;

                default:
                    functionCode = 3;
                    break;

            }
        }

        private void reg_data_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {

        }


        private bool keepReading = false; // 类字段，用于控制循环读取
        private async void remain_reading_Click(object sender, EventArgs e)
        {
            if (remain_reading.Text == "实时读取")
            {
                remain_reading.Text = "取消读取";
                keepReading = true;

                // 启动循环读取任务（异步执行，不阻塞 UI）
                
                
                    while (keepReading && tcpClient != null && tcpClient.Connected)
                    {
                        SendModbusRequest(); // 发送请求

                        // 在这里更新 DataGridView 的内容
                        UpdateDataGridView(); // 需要实现的方法，确保在 UI 线程中调用

                        await Task.Delay(1000); // 等待 2 秒，可根据需求调整频率
                    
                };
            }
            else
            {
                // 停止循环读取
                remain_reading.Text = "实时读取";
                keepReading = false;
            }
        }

        private void UpdateDataGridView()
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action(UpdateDataGridView)); // 在 UI 线程中调用
            }

                
            
        }
    }
}


